#if !defined(DB_CONNECTION_POOL_H)
#define DB_CONNECTION_POOL_H

#include "locker.h"
#include <list>
#include <mysql-cppconn-8/mysql/jdbc.h>
#include <string>

class db_connection_pool
{
private:
    /// @brief 池中最大连接数量
    uint8_t MaxConn;
    /// @brief 当前已建立的连接数量
    uint8_t CurConn;
    /// @brief 当前空闲的连接数量
    uint8_t FreeConn;

    /// @brief 线程锁
    locker lock;
    /// @brief 信号量
    sem reserve;

    /// @brief 数据库池对象（单例）
    static db_connection_pool *connPool;
    /// @brief 数据库驱动
    sql::Driver *driver;
    /// @brief 连接池队列容器
    std::list<sql::Connection *> connList;

    /// @brief 数据库地址
    std::string URL;
    /// @brief 数据库端口
    std::string PORT;
    /// @brief 数据库用户名
    std::string USER;
    /// @brief 数据库密码
    std::string PASSWORD;
    /// @brief 数据库名称
    std::string DBNAME;

private:
    /// @brief 创建数据库连接
    /// @return
    sql::Connection *CreateConnection();

public:
    /// @brief 获取数据库连接池唯一对象
    /// @return
    static db_connection_pool *GetInstance(std::string url, std::string user, std::string passwd, std::string db_name, int port, uint8_t max_conn);

    /// @brief 从池中获取空闲连接
    /// @return
    sql::Connection *GetConnection();

    /// @brief 销毁数据库连接
    /// @param conn
    /// @return
    bool ReleaseConnect(sql::Connection *conn);

    /// @brief 获取空闲连接数量
    /// @return
    inline int GetFreeConn() { return FreeConn; };

    /// @brief 销毁池
    void DestroyPool();

    ~db_connection_pool() { this->DestroyPool(); };

private:
    db_connection_pool(std::string url, std::string user, std::string passwd, std::string db_name, int port, uint8_t max_conn);
};

class connRAII
{
public:
    /// @brief RAII获取连接
    /// @param conn 双指针修改数据库连接
    /// @param connPool
    connRAII(sql::Connection **conn, db_connection_pool *connPool);

    /// @brief RAII回收连接
    ~connRAII();

private:
    sql::Connection *conRAII;
    db_connection_pool *poolRAII;
};

#endif // DB_CONNECTION_POOL_H
